package com.tao.service.impl.Mq;

//@RabbitListener(bindings =@QueueBinding(
//        // email.Deract.queue 是队列名字，这个名字你可以自定随便定义。
//        value = @Queue(value = "msg.topic.queue",autoDelete = "false"),
//        // order.Deract 交换机的名字 必须和生产者保持一致
//        exchange = @Exchange(value = "direct-exchange-boot",
//                // 这里是确定的rabbitmq模式是：Deract 是以广播模式 、 发布订阅模式
//                type = ExchangeTypes.DIRECT)
//))


import com.rabbitmq.client.Channel;
import com.tao.pojo.Miaosha;
import com.tao.pojo.Submittable;
import com.tao.service.MiaoshaService;
import com.tao.service.SubmittableService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Date;


// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
@Component
public class MiaoshaReceiveService {
    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    MiaoshaService miaoshaService;

    @Autowired
    SubmittableService submittableService;

    /*
    有exchange交换机则用，没有则创建，而且队列是临时队列
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
//                    value = @Queue(value = "QUEUE_All",,autoDelete = "false"),
                    exchange = @Exchange(value = "miaoshaSyt",type = "topic"),
                    key = {"#.miaoshaSyt.#"}
//                    即使如  topic.miaoshaSyt.id   也可以   #.id.#  获取到；
//                    # 任意个，  *一个词   都由点分割
            )

    })
    //rabbit mq测试  topic  #.miaoshaSyt.#
    public void MiaoshaSytReceive(Miaosha miaosha){
        // 此处省略发邮件的逻辑
        System.out.println("MiaoshaSytReceive1-------------->" + miaosha.toString());
    }

//
//    //rabbit  绑定 aid 和qid的    提交submit
//    @RabbitListener(bindings = {
//            @QueueBinding(
//                    value = @Queue,
//                    exchange = @Exchange(value = "submitTable.miaosha",type = "topic"),
//                    key = {"#.submitTable.#"}
//            )
//    })
//    @Transactional
//    public void SubmitTableReceive1(Submittable submittable){
//        miaoshaService.reduceMiaoshaSum(submittable.getAid(),1);
//        submittableService.save(submittable);
//        System.out.println("接收秒杀数据qid  aid的-------------->" + submittable.toString());
//    }
//


    //1的 翻版，消息确认
    //@RabbitHandler注解标注的方法要增加 channel(信道)、message 两个参数。
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "submitTable.miaosha",type = "topic"),
                    key = {"#.submitTable.#"}
            )
    })

    @Transactional
    @RabbitHandler
    public void SubmitTableReceive2(Submittable submittable, Channel channel, Message message) throws IOException{
        try {
//            获取库存（redis）判断是否还有
            int miaoshaSum = miaoshaService.getMiaoshaSum(submittable.getAid());

            if (miaoshaSum<=0){
//                如果库存不足，拒绝接收
                logger.error(submittable.getAid()+"库存已经无了");
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            miaoshaService.reduceMiaoshaSum(submittable.getAid(),1);
            submittableService.save(submittable);
//            System.out.println("Receive2:秒杀数据已接受，并且确认-------------->" + submittable.toString());

//            消息确认
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            /*  void basicAck(long deliveryTag, boolean multiple) 方法
                使用此回执方法后，消息会被rabbitmq broker 删除。
             */


//            // 拒绝消息之后 就会被删除
//            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {
            if (message.getMessageProperties().getRedelivered()) {

                logger.error("消息已重复处理失败,拒绝再次接收...");

                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
                /*
                basicReject 拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似。
                 */
            } else {

                logger.error("消息即将再次返回队列处理...");

                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                /*
                basicNack  表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列。
                 */
            }

        }

    }


//
//    @RabbitListener(bindings = {
//            @QueueBinding(
//                    value = @Queue,
//                    exchange = @Exchange(value = "miaoshaSyt",type = "topic"),
//                    key = {"#.id.#"}
//            )
//    })
//    // 秒杀下单  topic  #.id.#
//    public void MiaoshaSytReceive3(Miaosha miaosha){
//        miaoshaService.StByMs(Long.valueOf(miaosha.getId()));
//        System.out.println("3：下单id--------------> "+miaosha.getId() );
//    }
//




    // ********************************** 死信

}

/*
  请求发送到MQ(qid,aid)   ---》  MQ 接收(qid,qid) --aid-->miaoshaService  --aid-->submitService
                          \-->
 */